package net.nshc.kwkim.mycalc.util;

import java.util.*;

import android.util.*;

import net.nshc.kwkim.mycalc.*;

public class TokenizeFixConvert {
	public static Vector<Token> tokenize(String s)
	{
		Vector<Token> result = new Vector<Token>();
		int index = 0;            // index into s
		while (index < s.length())
			if (Character.isWhitespace(s.charAt(index)))
				index++;
			else if (Character.isDigit(s.charAt(index))) {
				StringBuffer digitSequence = new StringBuffer();
				while (index < s.length() && Character.isDigit(s.charAt(index))) {
					digitSequence.append(s.charAt(index));
					index++;
				}
				Token newToken = new Token(true, Integer.parseInt(digitSequence.toString()));
				result.addElement(newToken);
			}
			else {
				switch (s.charAt(index)) {
				case '+': 
					result.addElement(new Token(false, Token.ADD)); break;
				case '-': 
					result.addElement(new Token(false, Token.MINUS)); break;
				case '×':
					result.addElement(new Token(false, Token.MULTIPLY)); break;
				case '÷':
					result.addElement(new Token(false, Token.DIVIDE)); break;
				case 'p': 
					result.addElement(new Token(false, Token.POWER)); break;
				case 'q': 
					result.addElement(new Token(false, Token.SQRT)); break;
				case 's': 
					result.addElement(new Token(false, Token.SIN)); break;
				case 'c': 
					result.addElement(new Token(false, Token.COS)); break;
				case 't': 
					result.addElement(new Token(false, Token.TAN)); break;
				case 'l': 
					result.addElement(new Token(false, Token.LOG)); break;
				case 'n': 
					result.addElement(new Token(false, Token.NATURAL_LOG)); break;
				case 'f': 
					result.addElement(new Token(false, Token.FACTOFIAL)); break;
				case 'b': 
					result.addElement(new Token(false, Token.COMBINATION)); break;
				case 'x': 
					result.addElement(new Token(false, Token.ABSOLUTE_NUMBER)); break;
				case '(':
					result.addElement(new Token(false, Token.BRACKET_OPEN)); break;
				case ')':
					result.addElement(new Token(false, Token.BRACKET_CLOSE)); break;
				case ',': 
					result.addElement(new Token(false, Token.POWER_COMMA)); break;
				default:
					// Found a char that does not make sense.
					return null;
				}
				index++;
			}
		result.addElement(new Token(false, Token.END));
		return result;
	}

	public static Vector<Token> infixToPostfix(Vector<Token> infix)
	{
		Stack<Token> tokenStack = new Stack<Token>();
		tokenStack.push(new Token(false, Token.BEGIN));

		Vector<Token> result = new Vector<Token>();
		for (int i = 0; i < infix.size(); i++) {
			Token current = (Token) infix.elementAt(i);
			Log.d("CURRENT_TOKEN_IS", "Token = "+current);
			
			if (current.isNumber()){
				result.addElement(current);
				Log.d("CURRENT_TOKEN_IS", "Token is Number = "+current);
			}
			
			else if (current.kindOfOperator() == Token.ABSOLUTE_NUMBER || current.kindOfOperator() == Token.NEGATIVE_NUMBER ||
					current.kindOfOperator() == Token.SIN || current.kindOfOperator() == Token.COS || current.kindOfOperator() == Token.TAN || 
					current.kindOfOperator() == Token.FACTOFIAL || current.kindOfOperator() == Token.LOG || 
					current.kindOfOperator() == Token.NATURAL_LOG || current.kindOfOperator() == Token.SQRT)
				result.addElement(current);
			
			else if (current.kindOfOperator() == Token.BRACKET_OPEN)
				tokenStack.push(current);
			
			else if (current.kindOfOperator() == Token.BRACKET_CLOSE) {
				while (tokenStack.peek().kindOfOperator() != Token.BRACKET_OPEN) {
					Log.d("1CURRENT_TOKEN_IS", "Token is OPERATOR = "+current);
					Log.d("1TOKEN_POP_IS", "Token_POP = "+tokenStack.peek());
					result.addElement(tokenStack.pop());
//					tokenStack.pop();
				}
//				tokenStack.pop();
			}
			
			else {
				while (Token.preferLeft(tokenStack.peek(), current)) {
					Log.d("CURRENT_TOKEN_IS", "Token is OPERATOR = "+current);
					Log.d("TOKEN_POP_IS", "Token_POP = "+tokenStack.peek());
					result.addElement(tokenStack.pop());
//					tokenStack.pop();
				}
				tokenStack.push(current);
			}
		}
		return result;
	}
}
